package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.ProviderSchedule;
import com.ruoyi.common.core.domain.entity.ServiceProvider;
import com.ruoyi.common.core.domain.entity.ServiceReservation;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.ProviderScheduleMapper;
import com.ruoyi.system.mapper.ServiceProviderMapper;
import com.ruoyi.system.mapper.ServiceReservationMapper;
import com.ruoyi.system.service.IServiceReservationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ServiceReservationServiceImpl implements IServiceReservationService {

    private static final Logger log = LoggerFactory.getLogger(ServiceReservationServiceImpl.class);

    @Autowired
    private ServiceReservationMapper reservationMapper;

    @Autowired
    private ServiceProviderMapper providerMapper;

    @Autowired
    private ProviderScheduleMapper scheduleMapper;

    @Override
    public List<ServiceReservation> selectServiceReservationList(ServiceReservation reservation) {
        return reservationMapper.selectServiceReservationList(reservation);
    }

    @Override
    public ServiceReservation selectServiceReservationById(Long id) {
        return reservationMapper.selectServiceReservationById(id);
    }

    @Override
    @Transactional
    public AjaxResult insertServiceReservation(ServiceReservation reservation) {
        ServiceProvider provider = providerMapper.selectServiceProviderById(reservation.getProviderId());
        if (provider == null) {
            log.warn("服务人员不存在，ID: {}, 使用简化版预约方法", reservation.getProviderId());
            // 使用简化版的预约方法，绕过服务人员验证
            return insertSimpleReservation(reservation);
        }

        // 直接获取 LocalDate 和 LocalTime
        LocalDate reservationDate = reservation.getReservationDate();
        LocalTime reservationTime = reservation.getReservationTime();

        int count = reservationMapper.countReservationByProviderAndTime(
                reservation.getProviderId(), reservationDate, reservationTime);
        if (count > 0) {
            log.warn("该服务人员在指定时间已有预约: providerId={}, date={}, time={}", 
                    reservation.getProviderId(), reservationDate, reservationTime);
            return AjaxResult.error("该服务人员在指定时间已有预约");
        }

        if (!isProviderAvailable(provider, reservationDate, reservationTime)) {
            log.warn("该服务人员在指定时间不可用: providerId={}, date={}, time={}", 
                    reservation.getProviderId(), reservationDate, reservationTime);
            return AjaxResult.error("该服务人员在指定时间不可用");
        }

        reservation.setStatus("0");
        Date currentDate = new Date();
        reservation.setCreateBy(SecurityUtils.getUsername());
        reservation.setCreateTime(currentDate);

        log.info("开始插入预约记录: {}", reservation);
        int rows = reservationMapper.insertServiceReservation(reservation);
        if (rows > 0) {
            log.info("预约记录插入成功，ID: {}", reservation.getId());
            
            ProviderSchedule schedule = new ProviderSchedule();
            schedule.setProviderId(reservation.getProviderId());
            // 直接设置 LocalDate，无需转换
            schedule.setScheduleDate(reservationDate);
            schedule.setStartTime(reservationTime.toString());
            schedule.setEndTime(addOneHour(reservationTime));
            schedule.setStatus("0");
            schedule.setCreateBy(reservation.getCreateBy());
            schedule.setCreateTime(currentDate);
            
            log.info("开始插入服务人员排班记录: {}", schedule);
            scheduleMapper.insertProviderSchedule(schedule);

            // 返回成功结果，同时包含预约ID
            log.info("预约成功，返回预约ID: {}", reservation.getId());
            return AjaxResult.success("预约成功", reservation.getId());
        }
        log.error("预约失败");
        return AjaxResult.error("预约失败");
    }
    
    /**
     * 简化版的预约方法，绕过服务人员验证
     */
    private AjaxResult insertSimpleReservation(ServiceReservation reservation) {
        log.info("使用简化版预约方法，绕过服务人员验证");
        
        reservation.setStatus("0");
        Date currentDate = new Date();
        reservation.setCreateBy(SecurityUtils.getUsername());
        reservation.setCreateTime(currentDate);

        log.info("开始插入简化版预约记录: {}", reservation);
        int rows = reservationMapper.insertServiceReservation(reservation);
        if (rows > 0) {
            log.info("简化版预约记录插入成功，ID: {}", reservation.getId());
            // 返回成功结果，同时包含预约ID
            return AjaxResult.success("预约成功", reservation.getId());
        }
        log.error("简化版预约失败");
        return AjaxResult.error("预约失败");
    }

    @Override
    @Transactional
    public AjaxResult updateServiceReservation(ServiceReservation reservation) {
        ServiceReservation oldReservation = reservationMapper.selectServiceReservationById(reservation.getId());
        if (oldReservation == null) {
            return AjaxResult.error("预约记录不存在");
        }

        if (!"0".equals(oldReservation.getStatus())) {
            return AjaxResult.error("只有待确认状态的预约可以修改");
        }

        // 直接获取 LocalDate
        LocalDate oldDate = oldReservation.getReservationDate();
        LocalDate newDate = reservation.getReservationDate();

        if (!oldReservation.getProviderId().equals(reservation.getProviderId()) ||
                !oldDate.equals(newDate) ||
                !oldReservation.getReservationTime().equals(reservation.getReservationTime())) {

            ServiceProvider provider = providerMapper.selectServiceProviderById(reservation.getProviderId());
            if (provider == null) {
                return AjaxResult.error("服务人员不存在");
            }

            LocalDate reservationDate = newDate;
            LocalTime reservationTime = reservation.getReservationTime();

            int count = reservationMapper.countReservationByProviderAndTime(
                    reservation.getProviderId(), reservationDate, reservationTime);
            if (count > 0) {
                return AjaxResult.error("该服务人员在指定时间已有预约");
            }

            if (!isProviderAvailable(provider, reservationDate, reservationTime)) {
                return AjaxResult.error("该服务人员在指定时间不可用");
            }

            ProviderSchedule schedule = new ProviderSchedule();
            schedule.setId(oldReservation.getId());
            schedule.setProviderId(reservation.getProviderId());
            // 直接设置 LocalDate，无需转换
            schedule.setScheduleDate(reservationDate);
            schedule.setStartTime(reservationTime.toString());
            schedule.setEndTime(addOneHour(reservationTime));
            schedule.setUpdateBy(SecurityUtils.getUsername());
            schedule.setUpdateTime(new Date());
            scheduleMapper.updateProviderSchedule(schedule);
        }

        reservation.setUpdateBy(SecurityUtils.getUsername());
        reservation.setUpdateTime(new Date());

        int rows = reservationMapper.updateServiceReservation(reservation);
        return rows > 0 ? AjaxResult.success("更新成功") : AjaxResult.error("更新失败");
    }

    @Override
    @Transactional
    public AjaxResult cancelReservation(Long id, String cancelReason) {
        ServiceReservation reservation = reservationMapper.selectServiceReservationById(id);
        if (reservation == null) {
            return AjaxResult.error("预约记录不存在");
        }

        if (!"0".equals(reservation.getStatus()) && !"1".equals(reservation.getStatus())) {
            return AjaxResult.error("只有待确认和已确认状态的预约可以取消");
        }

        reservation.setStatus("3");
        reservation.setRemark(cancelReason);
        reservation.setUpdateBy(SecurityUtils.getUsername());
        reservation.setUpdateTime(new Date());

        int rows = reservationMapper.updateServiceReservation(reservation);
        if (rows > 0) {
            ProviderSchedule schedule = new ProviderSchedule();
            schedule.setId(id);
            schedule.setStatus("1");
            schedule.setUpdateBy(reservation.getUpdateBy());
            schedule.setUpdateTime(reservation.getUpdateTime());
            scheduleMapper.updateProviderSchedule(schedule);

            return AjaxResult.success("取消预约成功");
        }
        return AjaxResult.error("取消预约失败");
    }

    @Override
    public int deleteServiceReservationById(Long id) {
        return reservationMapper.deleteServiceReservationById(id);
    }

    @Override
    public int deleteServiceReservationByIds(Long[] ids) {
        return reservationMapper.deleteServiceReservationByIds(ids);
    }

    @Override
    public int deleteServiceReservationByIds(String ids) {
        Long[] idArray = Convert.toLongArray(ids);
        return reservationMapper.deleteServiceReservationByIds(idArray);
    }

    @Override
    public List<String> getAvailableTimeSlots(Long providerId, String dateStr) {
        List<String> availableTimes = new ArrayList<>();
        ServiceProvider provider = providerMapper.selectServiceProviderById(providerId);
        if (provider == null) {
            return availableTimes;
        }

        LocalDate appointmentDate = LocalDate.parse(dateStr);
        String workingDays = provider.getWorkingDays();
        if (workingDays == null || workingDays.isEmpty()) {
            return availableTimes;
        }

        int dayOfWeek = appointmentDate.getDayOfWeek().getValue();
        if (!workingDays.contains(String.valueOf(dayOfWeek))) {
            return availableTimes;
        }

        String workingHours = provider.getWorkingHours();
        if (workingHours == null || workingHours.isEmpty()) {
            workingHours = "09:00-18:00";
        }

        String[] hours = workingHours.split("-");
        LocalTime startTime = LocalTime.parse(hours[0]);
        LocalTime endTime = LocalTime.parse(hours[1]);

        // 转换 LocalDate 为 java.sql.Date
        java.sql.Date sqlDate = java.sql.Date.valueOf(appointmentDate);
        // 确保 mapper 方法参数类型匹配
        List<ProviderSchedule> schedules = scheduleMapper.selectProviderScheduleByDate(providerId, sqlDate);

        LocalTime currentTime = startTime;
        while (currentTime.isBefore(endTime)) {
            String timeSlot = currentTime.toString();
            boolean isBooked = schedules.stream().anyMatch(s ->
                    timeSlot.equals(s.getStartTime()) && "0".equals(s.getStatus()));
            if (!isBooked) {
                availableTimes.add(timeSlot);
            }
            currentTime = currentTime.plusHours(1);
        }

        return availableTimes;
    }

    private boolean isProviderAvailable(ServiceProvider provider, LocalDate reservationDate, LocalTime reservationTime) {
        String workingDays = provider.getWorkingDays();
        if (workingDays != null && !workingDays.isEmpty()) {
            int dayOfWeek = reservationDate.getDayOfWeek().getValue();
            if (!workingDays.contains(String.valueOf(dayOfWeek))) {
                return false;
            }
        }

        String workingHours = provider.getWorkingHours();
        if (workingHours != null && !workingHours.isEmpty()) {
            String[] hours = workingHours.split("-");
            LocalTime startTime = LocalTime.parse(hours[0]);
            LocalTime endTime = LocalTime.parse(hours[1]);
            return !reservationTime.isBefore(startTime) && reservationTime.isBefore(endTime);
        }

        return true;
    }

    private String addOneHour(LocalTime time) {
        return time.plusHours(1).toString();
    }

    @Override
    public AjaxResult updateReservationStatus(Long id, String status) {
        ServiceReservation reservation = reservationMapper.selectServiceReservationById(id);
        if (reservation == null) {
            return AjaxResult.error("预约记录不存在");
        }

        // 状态值验证
        if (!status.equals("0") && !status.equals("1") && !status.equals("2") && !status.equals("3")) {
            return AjaxResult.error("无效的状态值");
        }

        // 状态变更逻辑检查
        String currentStatus = reservation.getStatus();
        if (status.equals(currentStatus)) {
            return AjaxResult.success("状态未变化");
        }

        // 待确认 -> 已确认、已取消、已完成：允许
        // 已确认 -> 已取消、已完成：允许
        // 已取消 -> 不能变更
        // 已完成 -> 不能变更
        if ("2".equals(currentStatus) || "3".equals(currentStatus)) {
            return AjaxResult.error("当前状态不允许变更");
        }

        if ("1".equals(currentStatus) && "0".equals(status)) {
            return AjaxResult.error("已确认的预约不能变更为待确认");
        }

        reservation.setStatus(status);
        reservation.setUpdateBy(SecurityUtils.getUsername());
        reservation.setUpdateTime(new Date());

        int rows = reservationMapper.updateServiceReservation(reservation);

        // 如果状态变更为已取消，同时更新服务人员排班状态
        if ("2".equals(status) && rows > 0) {
            ProviderSchedule schedule = new ProviderSchedule();
            schedule.setId(id);
            schedule.setStatus("1"); // 1表示排班已取消
            schedule.setUpdateBy(reservation.getUpdateBy());
            schedule.setUpdateTime(reservation.getUpdateTime());
            scheduleMapper.updateProviderSchedule(schedule);
        }

        return rows > 0 ? AjaxResult.success("状态更新成功") : AjaxResult.error("状态更新失败");
    }
}